/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xos_http_protocol.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../impl/head.h"
#include "cookie_impl.h"
#include "objs.h"

namespace xos_http_protocol
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static cookie_impl::ITEM_DATA xos_item_data;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    cookie_impl::cookie_impl()
    {
        init_data();
    }

    cookie_impl::~cookie_impl()
    {}

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int cookie_impl::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    int cookie_impl::load( const char * lpszCookie, xos_box::i_list * pCookieList, session_impl ** ppv )
    {
        int ret = 0;

        xos_common::i_misc * pComMisc = mgr::container()->common()->misc();
        xos::i_crt * pCrt = mgr::container()->crt();

        if( !lpszCookie || !lpszCookie[0] )
        {
            return 1;
        }

        xos_box::i_buf * pBuf = 0;
        const char * pValue = 0;
        const char * pName = 0;
        char * pB = 0;
        char * pP = 0;
        int len = 0;
        cookie_impl * pCookie = 0;
        {
            pBuf = mgr::container()->box()->buf();
            pB = pBuf->get_data( 0, 0, 0, 0 );
            len = xos_box::i_buf::BUF_SIZE;
            pP = pB;
        }
        {
            pCrt->strcpy( pB, len, lpszCookie );
        }
        while( 1 )
        {
            char c = *pP;
            if( ( ';' == c ) || ( 0 == c ) )
            {
                *pP = 0;
                pValue = pB;
                pB = pP + 1;
                if( pName && pValue )
                {
                    char value[4096] = { 0 };
                    char name[1024] = { 0 };
                    pCrt->strcpy( value, sizeof( value ), pValue );
                    pCrt->strcpy( name, sizeof( name ), pName );
                    pComMisc->trim( value, " " );
                    pComMisc->trim( name, " " );
                    if( 0 == pCrt->strcmp( xos_http_protocol::HTTP_SESSION_ID, name ) )
                    {
                        session_impl * pSession = session_impl::get( value );
                        pSession->reset_timeout();
                        *ppv = pSession;
                    }
                    {
                        xos_stl::init_pool_item( pCookie );
                        pCookie->value( value );
                        pCookie->name( name );
                        pCookieList->push_back( pCookie );
                        pCookie = 0;
                    }
                    pValue = 0;
                    pName = 0;
                }
                if( 0 == c )
                {
                    break;
                }
            }
            else if( '=' == c )
            {
                *pP = 0;
                pName = pB;
                pB = pP + 1;
            }
            ++pP;
        }

        xos_stl::release_interface( pBuf );

        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int cookie_impl::fmt( char * pBuf, int & nLen, int & nPos, const std::string & name, const std::string & value )
    {
        int ret = 0;

        if( name.empty() || value.empty() )
        {
            return 1;
        }

        int len = mgr::container()->crt()->sprintf( pBuf + nPos, nLen, "%s=%s;", name.c_str(), value.c_str() );
        nLen -= len;
        nPos += len;

        return ret;
    }

    int cookie_impl::fmt( char * pBuf, int & nLen, int & nPos, const std::string & name, int value )
    {
        int ret = 0;

        int len = mgr::container()->crt()->sprintf( pBuf + nPos, nLen, "%s=%d;", name.c_str(), value );
        nLen -= len;
        nPos += len;

        return ret;
    }

    int cookie_impl::fmt( char * pBuf, int & nLen, int & nPos, const char * lpszValue )
    {
        int ret = 0;

        const char * pV = lpszValue;

        int len = mgr::container()->crt()->sprintf( pBuf + nPos, nLen, "%s;", pV );
        nLen -= len;
        nPos += len;

        return ret;
    }

    int cookie_impl::init_data()
    {
        int ret = 0;

        m_comment = "";
        m_domain = "";
        m_value = "";
        m_name = "";
        m_path = "/";
        m_bHttpOnly = true;
        m_bSecure = false;
        m_age = -1;
        m_ver = 0;

        m_cookie = "";

        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int cookie_impl::serial()
    {
        int ret = 0;

        xos_box::i_buf * pBuf = 0;
        char * pB = 0;
        int nLen = 0;
        int nPos = 0;

        {
            pBuf = mgr::container()->box()->buf();
            pB = pBuf->get_data( 0, 0, 0, 0 );
            nLen = xos_box::i_buf::BUF_SIZE;
        }

        fmt( pB, nLen, nPos, m_name, m_value );
        fmt( pB, nLen, nPos, "path", m_path );
        fmt( pB, nLen, nPos, "domain", m_domain );
        fmt( pB, nLen, nPos, "comment", m_comment );

        if( 0 != m_ver )
        {
            fmt( pB, nLen, nPos, "version", m_ver );
        }

        if( -1 != m_age )
        {
            fmt( pB, nLen, nPos, "max-age", m_age );
        }

        if( m_bHttpOnly )
        {
            fmt( pB, nLen, nPos, "HttpOnly" );
        }

        if( m_bSecure )
        {
            fmt( pB, nLen, nPos, "Secure");
        }

        m_cookie = pB;
        xos_stl::release_interface( pBuf );

        return ret;
    }

    int cookie_impl::init()
    {
        int ret = 0;
        {
            f_cookie fun = mgr::get()->cookie_callback(0);
            if( fun )
            {
                fun( this, true );
            }
        }
        return ret;
    }

    int cookie_impl::term()
    {
        int ret = 0;
        {
            f_cookie fun = mgr::get()->cookie_callback( 0 );
            if( fun )
            {
                fun( this, false );
            }
        }
        init_data();
        return ret;
    }


    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // i_cookie method
    // 

    const char * cookie_impl::name( const char * lpszName )
    {
        const char * lpStr = lpszName;
        std::string & str = m_name;
        if( lpStr )
        {
            str = lpStr;
        }
        return str.c_str();
    }

    const char * cookie_impl::value( const char * lpszValue )
    {
        const char * lpStr = lpszValue;
        std::string & str = m_value;
        if( lpStr )
        {
            str = lpStr;
        }
        return str.c_str();
    }

    const char * cookie_impl::path( const char * lpszPath )
    {
        const char * lpStr = lpszPath;
        std::string & str = m_path;
        if( lpStr )
        {
            str = lpStr;
        }
        return str.c_str();
    }

    const char * cookie_impl::domain( const char * lpszDomain )
    {
        const char * lpStr = lpszDomain;
        std::string & str = m_domain;
        if( lpStr )
        {
            str = lpStr;
        }
        return str.c_str();
    }

    const char * cookie_impl::comment( const char * lpszComment )
    {
        const char * lpStr = lpszComment;
        std::string & str = m_comment;
        if( lpStr )
        {
            str = lpStr;
        }
        return str.c_str();
    }

    bool cookie_impl::secure( bool bSecure, bool bSet )
    {
        bool bVal = bSecure;
        bool & val = m_bSecure;
        if( bSet )
        {
            val = bVal;
        }
        return val;
    }

    bool cookie_impl::http_only( bool bHttp, bool bSet )
    {
        bool bVal = bHttp;
        bool & val = m_bHttpOnly;
        if( bSet )
        {
            val = bVal;
        }
        return val;
    }

    int cookie_impl::version( int nVer, bool bSet )
    {
        int nVal = nVer;
        int & val = m_ver;
        if( bSet )
        {
            val = nVal;
        }
        return val;
    }

    int cookie_impl::age( int nAge, bool bSet )
    {
        int nVal = nAge;
        int & val = m_age;
        if( bSet )
        {
            val = nVal;
        }
        return val;
    }

} // xos_http_protocol
